using System.Text.Json;
using StackExchange.Redis;

namespace GEM.Infrastructure.Redis;

public class RedisService : IRedisService
{
    private readonly ConnectionMultiplexer _redis;
    private readonly IDatabase _db;

    //依赖注入
    public RedisService(string connString)
    {
        _redis = ConnectionMultiplexer.Connect(connString);
        _db = _redis.GetDatabase();
    }

    public async Task DeleteKeyAsync(string key)
    {
        await _db.KeyDeleteAsync(key);
    }

    public async Task ExpireKeyAsync(string key, TimeSpan? expiry = null)
    {
        await _db.KeyExpireAsync(key, expiry);
    }

    public async Task<string?> GetStringAsync(string key)
    {
        var value = await _db.StringGetAsync(key);
        return value.HasValue ? value.ToString() : null;
    }

    public async Task<HashEntry[]> HashGetAllAsync(string key)
    {
        var hashField = await Task.FromResult(_db.HashGetAll(key));
        return hashField;
    }

    public async Task<List<T>> HashGetAllObjectsAsync<T>(string key)
    {
        var hashEntries = await HashGetAllAsync(key);
        if (hashEntries == null || hashEntries.Length == 0)
            return new List<T>();

        return hashEntries
            .Select(entry => JsonSerializer.Deserialize<T>(entry.Value!))
            .Where(u => u != null)
            .Cast<T>()
            .ToList();
    }

    public async Task<string?> HashGetAsync(string key, string field)
    {
        var value = await _db.HashGetAsync(key, field);
        return value.HasValue ? value.ToString() : null;
    }

    public async Task<T?> HashGetObjectAsync<T>(string key, string field)
    {
        var json = await HashGetAsync(key, field);
        return json == null ? default : JsonSerializer.Deserialize<T>(json);
    }

    public async Task HashSetAsync(string key, string field, string value)
    {
        await _db.HashSetAsync(key, field, value);
    }

    public async Task HashSetObjectAsync<T>(string key, string field, T value)
    {
        var json = JsonSerializer.Serialize(value);
        await HashSetAsync(key, field, json);
    }

    public async Task SetStringAsync(string key, string value, TimeSpan? expiry = null)
    {
        await _db.StringSetAsync(key, value, expiry);
    }
}